package io.gitee.zhangbinhub.acp.boot.websocket.servlet

import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import org.springframework.web.socket.*
import java.nio.ByteBuffer

abstract class AcpWebSocketHandlerServlet(@JvmField protected val logAdapter: LogAdapter) : WebSocketHandler {
    @JvmField
    var session: WebSocketSession? = null
    private fun doSendMessage(message: WebSocketMessage<*>) {
        session!!.sendMessage(message)
    }

    fun sendMessage(message: String): Boolean = if (beforeSendMessage()) {
        try {
            doSendMessage(TextMessage(message))
            true
        } catch (e: Exception) {
            logAdapter.error(e.message, e)
            false
        }
    } else {
        false
    }

    fun sendMessage(message: ByteBuffer): Boolean = if (beforeSendMessage()) {
        try {
            doSendMessage(BinaryMessage(message))
            true
        } catch (e: Exception) {
            logAdapter.error(e.message, e)
            false
        }
    } else {
        false
    }

    private fun beforeSendMessage(): Boolean = if (session != null && session!!.isOpen) {
        true
    } else {
        logAdapter.error("WebSocket session is null or closed!")
        false
    }

    @Throws(IllegalStateException::class)
    override fun handleMessage(session: WebSocketSession, message: WebSocketMessage<*>) {
        when (message) {
            is TextMessage -> {
                receiveMessage(session, message.payload)
            }

            is BinaryMessage -> {
                receiveMessage(session, message.payload)
            }

            is PingMessage -> {
                session.sendMessage(PongMessage())
            }

            is PongMessage -> {
                logAdapter.debug("WebSocket server receive pong message")
            }

            else -> throw IllegalStateException("Unexpected WebSocket message type: $message")
        }
    }

    override fun handleTransportError(session: WebSocketSession, exception: Throwable) {
        sessionError(session, exception)
    }

    /**
     * 是否支持接收不完整的消息
     */
    override fun supportsPartialMessages(): Boolean = false

    abstract fun sessionOpen(session: WebSocketSession)
    abstract fun sessionClose(session: WebSocketSession?, closeStatus: CloseStatus)
    abstract fun sessionError(session: WebSocketSession?, throwable: Throwable?)
    abstract fun receiveMessage(session: WebSocketSession, message: String)
    abstract fun receiveMessage(session: WebSocketSession, message: ByteBuffer)
}